package com.gengzp.system.service.impl;

import com.gengzp.common.enums.ClientTypeEnum;
import com.gengzp.common.enums.ConsolePageEnum;
import com.gengzp.common.enums.YesNoEnum;
import com.gengzp.common.exception.BusinessException;
import com.gengzp.common.model.role.entity.SysRole;
import com.gengzp.common.model.user.entity.SysUser;
import com.gengzp.common.model.user.req.LoginSysUserReq;
import com.gengzp.common.model.user.req.RegisterSysUserReq;
import com.gengzp.common.model.user.resp.LoginSysUserResp;
import com.gengzp.common.utils.EncryptionUtils;
import com.gengzp.common.utils.SnowFlakeIdUtils;
import com.gengzp.common.utils.ThreadUtils;
import com.gengzp.permission.model.UserPrincipalModel;
import com.gengzp.permission.utils.PermissionUtils;
import com.gengzp.system.facade.PermissionFacade;
import com.gengzp.system.facade.SysRoleFacade;
import com.gengzp.system.mapper.SysUserMapper;
import com.gengzp.system.service.SysUserAuthorizationService;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @ClassName SysUserAuthorizationServiceImpl
 * @Description 系统用户授权服务层实现类
 * @Author gengzp
 * @Date 2025/9/8 15:36
 */
@Service
public class SysUserAuthorizationServiceImpl implements SysUserAuthorizationService {

    private static final Logger logger = LoggerFactory.getLogger(SysUserAuthorizationServiceImpl.class);

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PermissionFacade permissionFacade;

    @Autowired
    private SysRoleFacade sysRoleFacade;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginSysUserResp register(RegisterSysUserReq req) {
        // 账号昵称防重
        List<String> errorMessages = ThreadUtils.batchExecute(() -> {
            if (Objects.equals(req.getUserAccount(), PermissionUtils.getSuperAdminUserAccount()) ||
                    Objects.nonNull(sysUserMapper.selectSysUserByAccount(req.getUserAccount()))) {
                throw BusinessException.get("当前用户账号【】已被占用，无法重复创建");
            }
        }, () -> {
            if (Objects.equals(req.getUserNickname(), PermissionUtils.getSuperAdminNickname()) ||
                    Objects.nonNull(sysUserMapper.selectSysUserByNickname(req.getUserNickname()))) {
                throw BusinessException.get("当前用户昵称【】已被占用，无法重复创建");
            }
        });
        if (CollectionUtils.isNotEmpty(errorMessages)) {
            throw BusinessException.get(StringUtils.join(errorMessages, "；"));
        }

        SysUser sysUser = new SysUser();
        sysUser.setUserAccount(req.getUserAccount());
        sysUser.setUserNickname(req.getUserNickname());
        sysUser.setUserGender(req.getUserGender());
        // 使用随机uuid作为加密盐值, 为密码进行加密
        sysUser.setSalt(UUID.randomUUID().toString().replace("-", ""));
        sysUser.setUserPassword(
                EncryptionUtils.md5hex(req.getUserPassword() + sysUser.getSalt()));
        // 注册接口调用时一定是用户未登录状态, 因此 id, 创建人, 创建时间, 修改人, 修改时间 字段都需要手动填充
        sysUser.setId(SnowFlakeIdUtils.generateId());
        sysUser.setCreatedBy(sysUser.getId());
        sysUser.setCreatedTime(new Date());
        sysUser.setLastModifiedBy(sysUser.getId());
        sysUser.setLastModifiedTime(sysUser.getCreatedTime());
        sysUser.setIsDeleted(YesNoEnum.NO.getCode());

        // 用户落库
        sysUserMapper.insertSysUser(sysUser);
        // 注册完成后, 自动登录
        UserPrincipalModel userPrincipalModel = PermissionUtils.doLogin(
                sysUser.getId(), ClientTypeEnum.getValueByCode(req.getClientType()), Collections.EMPTY_LIST);

        // 组装登录完成后的返回信息
        LoginSysUserResp result = new LoginSysUserResp();
        result.setId(userPrincipalModel.getUserId());
        result.setUserAccount(sysUser.getUserAccount());
        result.setUserNickname(sysUser.getUserNickname());
        result.setToken(userPrincipalModel.getToken());
        result.setPagePermissionCodes(Lists.newArrayList());
        return result;
    }

    @Override
    public LoginSysUserResp login(LoginSysUserReq req) {
        long userId;
        String userNickname;
        String userPassword;
        String salt;

        // 是否为超级管理员标识
        boolean isSuperAdmin = Objects.equals(req.getUserAccount(), PermissionUtils.getSuperAdminUserAccount());
        if (isSuperAdmin) {
            userId = Long.parseLong(PermissionUtils.getSuperAdminUserId());
            userNickname = PermissionUtils.getSuperAdminNickname();
            userPassword = PermissionUtils.getSuperAdminUserPassword();
            salt = PermissionUtils.getSuperAdminUserSalt();
        } else {
            SysUser sysUser = sysUserMapper.selectSysUserByAccount(req.getUserAccount());
            if (Objects.isNull(sysUser)) {
                throw BusinessException.get("当前用户账号不存在");
            }
            userId = sysUser.getId();
            userNickname = sysUser.getUserNickname();
            userPassword = sysUser.getUserPassword();
            salt = sysUser.getSalt();
        }

        // 校验密码是否一致
        if (!Objects.equals(userPassword.toLowerCase(),
                EncryptionUtils.md5hex(req.getUserPassword() + salt).toLowerCase())) {
            throw BusinessException.get("密码错误");
        }

        // 当前用户关联的所有角色id
        List<Long> roleIds = permissionFacade.searchRoleIdsByUserId(userId);

        // 使用权限框架完成登录
        UserPrincipalModel userPrincipalModel = PermissionUtils.doLogin(
                userId, ClientTypeEnum.getValueByCode(req.getClientType()), roleIds);

        // 组装登录完成后的返回信息
        LoginSysUserResp result = new LoginSysUserResp();
        result.setId(String.valueOf(userId));
        result.setUserAccount(req.getUserAccount());
        result.setUserNickname(userNickname);
        result.setToken(userPrincipalModel.getToken());
        result.setPagePermissionCodes(Lists.newArrayList());
        // 填充页面权限
        fillInUserPagePermissions(result, roleIds, isSuperAdmin);

        return result;
    }

    @Override
    public void quit() {
        PermissionUtils.doQuit(PermissionUtils.getCurrentUserId(), PermissionUtils.getCurrentUserToken());
    }

    /**
     * 填充用户页面权限
     *
     * @param resp         用户登录返回信息
     * @param roleIds      用户关联角色id集合
     * @param isSuperAdmin 是否为超级管理员
     */
    private void fillInUserPagePermissions(LoginSysUserResp resp, List<Long> roleIds, boolean isSuperAdmin) {
        // 根据关联的角色id查询所有的页面权限
        if (isSuperAdmin) {
            resp.getPagePermissionCodes().addAll(
                    Arrays.stream(ConsolePageEnum.values())
                            .map(ConsolePageEnum::getCode).toList());
            return;
        }

        if (CollectionUtils.isNotEmpty(roleIds)) {
            List<SysRole> sysRoles = sysRoleFacade.searchSysRolesByIds(roleIds);
            if (CollectionUtils.isEmpty(sysRoles)) {
                return;
            }
            resp.getPagePermissionCodes().addAll(
                    sysRoles.stream().map(SysRole::getConsolePageCodes)
                            .filter(StringUtils::isNotBlank).map(v -> v.split(","))
                            .flatMap(Arrays::stream).distinct().toList()
            );
        }
    }

}
